home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’97 / Brought to you by... / Source-n-stuff / main.c < prev    next >
Encoding:
Text File  |  1997-06-28  |  8.3 KB  |  309 lines  |  [TEXT/CWIE]

  1. // File "main.c" - 
  2.  
  3. #include <GestaltEqu.h>
  4. #include <TextServices.h>
  5. #include <Traps.h>
  6.  
  7. #include "main.h"
  8. #include "aevents.h"
  9. #include "filter.h"
  10. #include "floaters.h"
  11. #include "notify.h"
  12. #include "patches.h"
  13. #include "sample win.h"
  14.  
  15. // * ****************************************************************************** *
  16. // Global Declarations
  17.  
  18. GlobalsRec glob;
  19.  
  20. void ShowSponsorship();
  21. void SplashIdle();
  22.  
  23. // * ****************************************************************************** *
  24. // * ****************************************************************************** *
  25.  
  26. void DoTest() {
  27.     short i;
  28.     long response;
  29.     
  30.     for(i=0; i<sizeof(glob); ((char *) &glob)[i++] = 0);
  31.     
  32.     // Simple Tests for compatibility
  33.     if (Gestalt(gestaltSystemVersion, &response) || (response < 0x0604) ||
  34.             Gestalt(gestaltTSMgrVersion, &response))
  35.         UserNotify(kNotifyStringList, kSys71NotifyString, TRUE);
  36.         
  37.     // I could look at my ProcessInfoRec, but this is a single line solution
  38.     glob.bkgdOnly = ((** (short **) GetResource('SIZE', -1)) & 0x0400) ? TRUE : FALSE;
  39.     glob.hasColorQD = (! Gestalt(gestaltQuickdrawFeatures, &response) &&
  40.             (response & (1 << gestaltHasColor))) ? TRUE : FALSE;
  41.     glob.hasGDevices = (NGetTrapAddress(_GetDeviceList, ToolTrap) !=
  42.             NGetTrapAddress(_Unimplemented, ToolTrap)) ? TRUE : FALSE;
  43.     glob.hasDragMgr = (! Gestalt(gestaltDragMgrAttr, &response) &&
  44.             (response & (1 << gestaltDragMgrPresent))) ? TRUE : FALSE;
  45.  
  46.     // Inform the user how to find the "TSM Fix" if it isn't installed
  47.     if (Gestalt('TSM+', &response))
  48.         UserNotify(kNotifyStringList, kTSMFixNotifyString, FALSE);
  49.     }
  50.  
  51. // * ****************************************************************************** *
  52. // * ****************************************************************************** *
  53.  
  54. void DoInit() {
  55.     long saveA5;
  56.     
  57.     // 'appe' programs get 8k of Stack Space by default -- we need MORE! 
  58.     if (glob.bkgdOnly) SetApplLimit(GetApplLimit() - 16384);
  59.     MaxApplZone();
  60.     MoreMasters();
  61.  
  62.     // Basic Initialization 
  63.     InitGraf(&qd.thePort);
  64.     
  65.     // Finish our Initialization - but only if we are a foreground app. Apple
  66.     //   warns loudly that bkgd-only apps should not call InitWindows(), etc.
  67.     if (! glob.bkgdOnly) {
  68.         InitFonts();
  69.         InitWindows();
  70.         InitMenus();
  71.         TEInit();
  72.         InitDialogs(0);
  73.         InitCursor();
  74.         
  75.         InsertMenu(GetMenu(kAppleMenuID), 0);
  76.         AddResMenu(GetMHandle(kAppleMenuID), 'DRVR');
  77.         InsertMenu(GetMenu(kFileMenuID), 0);
  78.         InsertMenu(GetMenu(kEditMenuID), 0);
  79.         DisableItem(GetMHandle(kEditMenuID), 0);
  80.         
  81.         DrawMenuBar();
  82.         }
  83.       else {
  84.         // After reading the above, you know that you can't call any other toolbox
  85.         //   init stuff. However, FindServiceWindow() fails if the MenuList lomem 
  86.         //   global is NIL! This is a moderate (but not recommended) workaround.
  87.         InitFonts();
  88.         InitMenus();
  89.         }
  90.     
  91.     PatchNewWindow();
  92.     PatchExitToShell();
  93.  
  94.     // Save this information for later
  95.     GetCurrentProcess(&glob.myPSN);    
  96.         
  97.     // Install an event filter or die
  98.     SetA5(saveA5 = SetA5(0));
  99.     glob.filterProc =
  100.             (Ptr) InstallEventFilter((FilterHelperUPP) EventFilterHelper, (Ptr) saveA5);
  101.     if (! glob.filterProc)
  102.         UserNotify(kNotifyStringList, kJGNENotifyString, TRUE);
  103.     
  104.     InitHLEvents();
  105.     NewSampleWindow();
  106.     }
  107.  
  108. // * ****************************************************************************** *
  109. // * ****************************************************************************** *
  110. long    gNextAdTicks = 0;
  111.  
  112. void DoLoop() {
  113.     Boolean floaterEvent;
  114.     
  115.     SplashIdle();    //call the first time before wait next event
  116.     
  117.     while(! glob.quitting) {
  118.         // If there are no internal events pending, then we call WNE() with a
  119.         //   moderate delay. Otherwise, we want to make a fast response to any 
  120.         //   floater events, so we make sure the event filter will wake us up quickly.
  121.         if(!gNextAdTicks)
  122.             gNextAdTicks = TickCount() + 600;
  123.         
  124.         if(TickCount() > gNextAdTicks)
  125.         {
  126.             ShowSponsorship();
  127.             gNextAdTicks = TickCount() + 1200;
  128.         }
  129.  
  130.         SplashIdle();
  131.         
  132.         if (! glob.forwardedEvents.qHead) 
  133.             WaitNextEvent(everyEvent, &glob.theEvent, 150, 0);    // Sleep for 2.5 secs
  134.         
  135.         // If nothing to do, then check our private event queue to see if any
  136.         //   clicks or keydowns are pending for our floater windows.
  137.         floaterEvent = (glob.theEvent.what != nullEvent) ? FALSE : 
  138.                 GetFloaterEvent(&glob.theEvent);
  139.         
  140.         // Check the states of our floaters, then generate and handle any 
  141.         //   pending Update Events for floaters because the Event Mgr will
  142.         //   not generate them for us.
  143.         ShowHideFloater(0);
  144.         UpdateFloater(0);
  145.  
  146.         switch(glob.theEvent.what) {
  147.             case nullEvent:
  148.                 break;
  149.             case mouseDown: {
  150.                 short thePart;
  151.                 Rect bounds;
  152.                 WindowPtr whichWin, frontWin;
  153.                 
  154.                 if (floaterEvent) {
  155.                     thePart = FindServiceWindow(glob.theEvent.where, &whichWin);
  156.                     if (GetFrontServiceWindow(&frontWin)) frontWin = 0;
  157.                     }
  158.                   else {
  159.                     thePart = FindWindow(glob.theEvent.where, &whichWin);
  160.                     frontWin = FrontWindow();
  161.                     }
  162.  
  163.                 glob.theEvent.message = thePart;        
  164.                 switch(thePart) {
  165.                     case inMenuBar:
  166.                         DoMenuItem(MenuSelect(glob.theEvent.where));
  167.                         break;
  168.                         
  169.                     case inSysWindow:
  170.                         SystemClick(&glob.theEvent, whichWin);
  171.                         break;
  172.                         
  173.                     case inDrag:
  174.                         if (whichWin != frontWin) {
  175.                             SelectWindow(whichWin);
  176.                             UpdateFloater(whichWin);
  177.                             }
  178.                         bounds = (*GetGrayRgn())->rgnBBox;
  179.                         DragWindow(whichWin, glob.theEvent.where, &bounds);
  180.                         UpdateFloater(whichWin);
  181.                         break;
  182.                         
  183.                     case inContent:
  184.                     case inGrow:
  185.                     case inGoAway:
  186.                     case inZoomIn:
  187.                     case inZoomOut:
  188.                         if (whichWin != frontWin) {
  189.                             SelectWindow(whichWin);
  190.                             UpdateFloater(whichWin);
  191.                             }
  192.                         EventDispatchFloaters(&glob.theEvent, whichWin);
  193.                         break;
  194.                     }
  195.                 break;
  196.                 }
  197.             case keyDown:
  198.             case autoKey: {
  199.                 char theKey, theChar;
  200.                 
  201.                 theChar = glob.theEvent.message & charCodeMask;
  202.                 theKey = (glob.theEvent.message & keyCodeMask) >> 8;
  203.                 
  204.                 if (glob.theEvent.modifiers & cmdKey)
  205.                     DoMenuItem(MenuKey(glob.theEvent.message & charCodeMask));
  206.                   else EventDispatchFloaters(&glob.theEvent, 0);
  207.                 }
  208.                 break;
  209.                     
  210.             case updateEvt:
  211.                 if (GetOneFloater((WindowPtr) glob.theEvent.message, FALSE))
  212.                     EventDispatchFloaters(&glob.theEvent, (WindowPtr) glob.theEvent.message);
  213.                 break;
  214.             case activateEvt:
  215.                 break;
  216.             case kHighLevelEvent:
  217.                 AEProcessAppleEvent(&glob.theEvent);
  218.                 break;
  219.             }
  220.         
  221.         // WARNING: Dont set the cursor to arrow just because it is over a floater
  222.         //   window -- most foreground apps are not smart enough to recognize a
  223.         //   the TSM floaters, and the cursor may start to flicker.
  224.         if (! glob.bkgdOnly) SetCursor(&qd.arrow);
  225.         }
  226.     }
  227.  
  228. // * ****************************************************************************** *
  229. // * ****************************************************************************** *
  230.  
  231. void DoMenuItem(long theMenuAndItem) {
  232.     short theMenu, theItem;
  233.     Str63 theString;
  234.     
  235.     if (! theMenuAndItem) return;
  236.     
  237.     theMenu = (theMenuAndItem & 0xFFFF0000) >> 16;
  238.     theItem = theMenuAndItem & 0x0000FFFF;
  239.     
  240.     switch(theMenu) {
  241.         case kAppleMenuID:
  242.             if (theItem == kAppleMenuAboutItem) {
  243.                 // Block out the floaters while we display our about box... 
  244.                 //   then enable and update them after we have finished.
  245.                 glob.modalFloats = TRUE;
  246.                 ShowHideFloater(0);
  247.                 
  248.                 Alert(128, 0);
  249.                 
  250.                 glob.modalFloats = FALSE;
  251.                 ShowHideFloater(0);
  252.                 UpdateFloater(0);
  253.                 }
  254.               else {
  255.                 GetItem(GetMHandle(theMenu), theItem, theString);
  256.                 OpenDeskAcc(theString);
  257.                 }
  258.             break;
  259.             
  260.         case kFileMenuID:
  261.             switch(theItem) {
  262.                 case kFileMenuNewItem:
  263.                     NewSampleWindow();
  264.                     break;
  265.                 case kFileMenuQuitItem:
  266.                     glob.quitting = TRUE;
  267.                     break;
  268.                 }
  269.             break;
  270.             
  271.         case kEditMenuID:
  272.             break;
  273.  
  274.         default:
  275.             break;
  276.         }
  277.     HiliteMenu(0);
  278.     DrawMenuBar();
  279.     }
  280.  
  281. // * ****************************************************************************** *
  282. // * ****************************************************************************** *
  283.  
  284. void DoDispose() {
  285.     static Boolean done = FALSE;
  286.     
  287.     // Our ExitToShell() patch may cause re-entrancy problems... so we bracket
  288.     //   the functional calls by checking and setting a one-time flag.
  289.     if (! done) {
  290.         done = TRUE;
  291.         
  292.         CloseRemainingFloaters();
  293.         
  294.         ReleaseEventFilter(glob.filterProc);
  295.         glob.filterProc = 0;
  296.         }
  297.     }
  298.         
  299. // * ****************************************************************************** *
  300. // * ****************************************************************************** *
  301.  
  302. void main() {
  303.     DoTest();
  304.     DoInit();
  305.     DoLoop();
  306.     DoDispose();
  307.     }
  308.     
  309.